home *** CD-ROM | disk | FTP | other *** search
-
- /*
- * QSORT.C
- *
- * (c)Copyright 1992-1997 Obvious Implementations Corp. Redistribution and
- * use is allowed under the terms of the DICE-LICENSE FILE,
- * DICE-LICENSE.TXT.
- *
- * Well, I actually implement a merge sort here, because I have no idea
- * how much stack is available for a quick sort.
- */
-
- #include <stdlib.h>
- #include <string.h>
-
- void
- qsort(base, elms, elmSize, cmpfunc)
- void *base;
- size_t elms;
- size_t elmSize;
- int (*cmpfunc)(const void *, const void *);
- {
- long i, j;
- void *tmp = malloc(elmSize);
-
- if (tmp == NULL)
- return;
-
- for (i = 2; (i >> 1) < elms; i *= 2) { /* merge sets of 2,4,8.. */
- for (j = 0; j < elms; j += i) {
- long i1 = i >> 1;
- long i2 = i1;
- char *p1;
- char *p2;
-
- if (elmSize == 4) {
- p1 = (char *)base + j * 4;
- p2 = p1 + i1 * 4;
- } else {
- p1 = (char *)base + j * elmSize;
- p2 = p1 + i1 * elmSize;
- }
-
- if (j + i1 + i2 > elms)
- i2 = elms - i1 - j;
-
- /*
- * Merge p2/i2 into p1/i1 until p2/i2 is exausted. Note that
- * i2 might start out negative (in which case i1 is invalid,
- * but the segment is already sorted anyway)
- */
-
- while (i2 > 0 && i1 > 0) {
- /*
- * compare current p1/i1 with next p2/i2. Skip p1 while
- * p1 < p2. Otherwise, merge the p2/i2 element into
- * p1/i1.
- */
-
- if ((*cmpfunc)(p1, p2) <= 0) {
- --i1;
- p1 += elmSize;
- } else {
- if (elmSize == 4) {
- *(long *)tmp = *(long *)p2;
- movmem(p1, p1 + 4, i1 * 4);
- *(long *)p1 = *(long *)tmp;
- } else {
- movmem(p2, tmp, elmSize);
- movmem(p1, p1 + elmSize, i1 * elmSize);
- movmem(tmp, p1, elmSize);
- }
- --i2;
- p2 += elmSize;
- p1 += elmSize; /* shifted p1, i1 stays */
- }
- }
- }
- }
- free(tmp);
- }
-
-